#pragma once

#include "localcommon.hpp"
#include <unordered_map>
#include <sstream>

namespace Local_Http
{
    const static std::string Hspace = " ";
    const static std::string Hblankline = "\r\n";
    const static std::string Hblanklines = "\r\n\r\n";
    const static std::string Hdelimiitre = ": ";

    const static std::string path = "./wwwroot";
    const static std::string name = "index.html";
    const static std::string pathname = "./wwwroot/index.html";
    const static std::string _404name = "./wwwroot/404.html";

    /// @brief heep请求
    class Request
    {
    public:
        /**************Request***************** */
        Request() {}
        ~Request() {}
        /**************Member***************** */
        std::string Serialization()
        {
            std::string lo_ret;

            return lo_ret;
        }
        bool Deserialization(std::string &message)
        {
            // 获得1行
            std::string lo_line;

            int ret_fin = message.find(Hblankline);
            if (ret_fin == std::string::npos)
            {
                return false;
            }
            lo_line = message.substr(0, ret_fin);
            // std::cout << "---------Deserialization::lo_line---------" << std::endl;
            // std::cout << lo_line << std::endl;
            // std::cout << "---------------------------" << std::endl;
            // 字符串流
            std::stringstream lo_ss(message);
            lo_ss >> _method >> _url >> _version;
            // std::cout << "---------Deserialization::this---------" << std::endl;
            // std::cout << _method << std::endl;
            // std::cout << _url << std::endl;
            // std::cout << _version << std::endl;
            // std::cout << "---------------------------" << std::endl;

            return false;
        }
        /**************Get***************** */
        std::string GetMethod() { return _method; }
        std::string GetUrl()
        {
            if (_url.size() == 1)
            {
                return pathname;
            }
            else
            {
                return path + _url;
            }
        }
        std::string GetVersion() { return _version; }
        /**************Set***************** */
        /**************Debug***************** */
        void print()
        {
            std::cout << "_method -> " << _method << std::endl;
            std::cout << "_url -> " << _url << std::endl;
            std::cout << "_version -> " << _version << std::endl;
        }

    private:
        std::string _method;
        std::string _url;
        std::string _version;

        std::unordered_map<std::string, std::string> _headers;
        std::string _blankline;
        std::string _text;
    };

    /// @brief http应答
    class Response
    {
    public:
        /**************Request***************** */
        Response() : _blankline(Hblankline) {}
        ~Response() {}
        /**************Member***************** */
        std::string Serialization()
        {
            std::string lo_ret = _version + Hspace + std::to_string(_code) + Hspace + _desc + Hblankline;
            for (auto &header : _headers)
            {
                lo_ret += (header.first + Hdelimiitre + header.second + Hblankline);
            }
            lo_ret += _blankline;
            lo_ret += _text;

            return lo_ret;
        }
        bool Deserialization(std::string &message)
        {
            return false;
        }
        bool MakeResponse()
        {
            //     if (_targetfile == "./wwwroot/favicon.ico")
            //     {
            //         Local_Log::LOG(Local_Log::LogLever::LFATAL) << "favicon error";
            //         return false;
            //     }
            int ret_res = ReadFileContent(_targetfile, &_text);
            if (!ret_res)
            {
                Local_Log::LOG(Local_Log::LogLever::LFATAL) << "404 error";
                SetCode(404);
                ReadFileContent(_404name, &_text);
                SetHeader("Content-Length", std::to_string(GetLength(_404name)));
                SetHeader("Content-Type", GetType(_404name));
            }
            else
            {
                Local_Log::LOG(Local_Log::LogLever::LFATAL) << "OK success";
                SetCode(200);
                ReadFileContent(_targetfile, &_text);
                SetHeader("Content-Length", std::to_string(GetLength(_targetfile)));
                SetHeader("Content-Type", GetType(_targetfile));
            }
            return true;
        }
        /**************Get***************** */
        /**************Set***************** */
        // target 目标
        void
        SetTargetFile(const std::string &target)
        {
            _targetfile = target;
        }
        void SetVersion(const std::string &version)
        {
            _version = version;
        }
        void SetCode(int code)
        {
            _code = code;
            switch (_code)
            {
            case 200:
                _desc = "OK";
                break;
            case 404:
                _desc = "Not Found";
                break;
            default:
                break;
            }
        }
        /**************Debug***************** */
        void SetHeader(const std::string &key, const std::string &value)
        {
            _headers[key] = value;
        }
        std::string GetType(const std::string &targetfile)
        {
            auto pos = targetfile.rfind(".");
            if (pos == std::string::npos)
            {
                return "text/html";
            }

            std::string suffix = targetfile.substr(pos);
            if (suffix == ".html" || suffix == ".htm")
                return "text/html";
            else if (suffix == ".jpg")
                return "image/jpeg";
            else if (suffix == "png")
                return "image/png";
            else
                return "text/html";
        }
        int GetLength(const std::string &pathname)
        {
            return FileSize(pathname);
        }
        /**************Debug***************** */
        void print()
        {
            std::cout << "_version -> " << _version << std::endl;
            std::cout << "_code -> " << _code << std::endl;
            std::cout << "_desc -> " << _desc << std::endl;
            std::cout << "_targetfile -> " << _targetfile << std::endl;
            for (auto it : _headers)
            {
                std::cout << it.first << " -> " << it.second << std::endl;
            }
        }

    private:
        std::string _version;
        int _code;
        std::string _desc;

        std::unordered_map<std::string, std::string> _headers;
        std::string _blankline;
        std::string _text;

        // 其他属性
        std::string _targetfile;
    };

    /// @brief http任务
    class Http
    {
    public:
        /**************Request***************** */
        Http(uint16_t port) : _tcpser(std::make_unique<Local_TcpSer::TcpServer>(port)) {}
        ~Http() {}
        /**************MemberServer***************** */
        bool GetContenLen(std::shared_ptr<Local_Sock_Mod::Socket> &sockfd, Local_Inetaddr::Inetaddr &client, Request *ptr_req)
        {
            std::string lo_reads;
            std::string lo_readhead;
            std::string lo_readtext;
            while (1)
            {
                int ret_rec = sockfd->Recv(&lo_reads);
                if (ret_rec > 0)
                {
                    // 获得表头
                    int ret_fin = lo_reads.find(Hblanklines);

                    if (ret_fin == std::string::npos)
                        continue;
                    std::string lo_reqhead = lo_reads.substr(0, ret_fin);
                    // std::cout << "---------GetContenLen::lo_reqhead---------" << std::endl;
                    // std::cout << lo_reqhead << std::endl;
                    // std::cout << "---------------------------" << std::endl;
                    ptr_req->Deserialization(lo_reqhead);
                    lo_reads.erase(0, ret_fin + Hblanklines.size());
                    // 获得内容

                    // std::cout << "---------Deserialization::ptr_req---------" << std::endl;
                    // ptr_req->print();
                    // std::cout << "---------------------------" << std::endl;

                    // std::cout << "---------GetContenLen::lo_reads---------" << std::endl;
                    // std::cout << lo_reads << " " << lo_reads.size() << std::endl;
                    // std::cout << "---------------------------" << std::endl;

                    return true;
                }
                return false;
            }
        }
        void GetRequest(std::shared_ptr<Local_Sock_Mod::Socket> &sockfd, Local_Inetaddr::Inetaddr &client)
        {
            // 获得报头
            Request lo_req;
            bool ret_getlen = GetContenLen(sockfd, client, &lo_req);
            std::cout << "-----Request------" << std::endl;

            if (ret_getlen)
            {
                std::cout << "-----GetRequest::lo_req------" << std::endl;
                lo_req.print();
                std::cout << "------------------" << std::endl;

                // 获得 路径

                // 建立应答
                Response lo_resp;
                lo_resp.SetVersion(lo_req.GetVersion());
                // lo_resp._code = 200;
                // lo_resp._desc = "OK";

                // 序列化

                // 查找目录
                // std::string lo_filename = lo_req.GetUrl();
                // ReadFileContent(pathname, &(lo_resp._text));
                lo_resp.SetTargetFile(lo_req.GetUrl());
                lo_resp.MakeResponse();
                std::cout << "-----GetRequest::lo_resp------" << std::endl;
                lo_resp.print();
                std::cout << "------------------" << std::endl;
                // 找的了 读对应文件
                std::string lo_httpres = lo_resp.Serialization();
                std::cout << "-----Response------" << std::endl;
                sockfd->Send(lo_httpres);

                // 未找到 返回错误码
                int i;
                std::cin >> i;
            }
        }

        void SetResponse()
        {
        }
        void Start()
        {
            _tcpser->Start([this](std::shared_ptr<Local_Sock_Mod::Socket> &sockfd, Local_Inetaddr::Inetaddr &client)
                           { this->GetRequest(sockfd, client); });
        }
        /**************MemberClient***************** */
        /**************Get***************** */
        /**************Set***************** */
        /**************Debug***************** */
        // void DebugGetRequest(std::shared_ptr<Local_Sock_Mod::Socket> &sockfd, Local_Inetaddr::Inetaddr &client)
        // {
        //     std::string lo_httpreqstr;
        //     sockfd->Recv(&lo_httpreqstr);
        //     std::cout << "-----Request------" << std::endl;
        //     // 建立应答
        //     Response lo_resp;
        //     lo_resp._version = "HTTP/1.1";
        //     lo_resp._code = 200;
        //     lo_resp._desc = "OK";
        //     std::string lo_filename = pathname;
        //     ReadFileContent(pathname, &(lo_resp._text));
        //     std::string lo_httpres = lo_resp.Serialization();
        //     // std::string lo_ret_str = "<!DOCTYPE html>\
        //     //                             <html>\
        //     //                             <head>\
        //     //                             <title> 极简网页 | 2025 - 09 - 29 </title>\
        //     //                             <meta charset=\"UTF-8\">\
        //     //                             <style>body{font-family:sans-serif;margin:40px auto;max-width:600px;text-align:center;background:#f0f8ff;color:#333;line-height:1.6;}</style>\
        //     //                             </head>\
        //     //                             <body>\
        //     //                             <h1>HTTP/1.1极简示例</h1>\
        //     //                             <p>当前时间:<strong>2025年9月29日 星期一13:20</strong></p>\
        //     //                             <p>农历:<strong>乙巳蛇年 八月初八</strong></p>\
        //     //                             <hr>\
        //     //                             <p>这是一个符合HTTP/1.1协议的最简网页实现</p>\
        //     //                             <p>© 2025极简设计</p>\
        //     //                             </body>\
        //     //                             </html>";
        //     std::cout << "-----Response------" << std::endl;
        //     sockfd->Send(lo_httpres);
        // }

    private:
        std::unique_ptr<Local_TcpSer::TcpServer> _tcpser;
    };
}